import CryptoJS from 'crypto-js'
const SecretKey = CryptoJS.enc.Utf8.parse("1234567890abcdef"); // 密钥
const iv = CryptoJS.enc.Utf8.parse("abcdef1234567890"); // 偏移量
/**
 * 获取数据类型
 * @param {*} da 
 */
function getDateType(da){
	let type = Object.prototype.toString.call(da)
	switch(type){
	    case '[object String]': return 'string'
	    case '[object Array]': return 'array'
	    case '[object Number]': return 'number'
	    case '[object Boolean]': return 'boolean'
	    case '[object Object]': return 'object'
	}
	return 'string'
}
/**
 * 加密对象
 * @param {*} data  数据对象
 * @param {*} encipherKey  是否启用字段名加密
 * @returns Object 加密后的对象
 */
export function encryption(data={},encipherKey=false){
	// console.log(SecretKey,SecretKey.toString())
	if(!data) return data
	let baseData = data
	try{
		baseData = JSON.parse(JSON.stringify(data))
		baseData.dataEncipherType='AES'
		const timeTemp = new Date().getTime()
		const verifyUseToObj = CryptoJS.MD5(JSON.stringify({
			// ...baseData,
			dataTimeTemp:timeTemp,
			SecretKey:SecretKey.toString(CryptoJS.enc.Base64),
			iv:iv.toString(CryptoJS.enc.Base64)
		})).toString()
			for (const key in baseData) {
			if (Object.hasOwnProperty.call(baseData, key)) {
				const value = baseData[key];
				if(value===undefined) continue;
				const valType = getDateType(value)
				const isString = valType =='string'
				const strVal = isString ? value:JSON.stringify(value)
				const keyVal = CryptoJS.AES.encrypt(strVal, SecretKey, {
					iv: iv,
					mode: CryptoJS.mode.CBC,
					padding: CryptoJS.pad.Pkcs7
				}).toString()
				if(encipherKey){
					const setKey = CryptoJS.AES.encrypt(key, SecretKey, {
						iv: iv,
						mode: CryptoJS.mode.CBC,
						padding: CryptoJS.pad.Pkcs7
					}).toString()
					delete baseData[key]
					baseData[setKey]=keyVal+(isString?'=;use':'=;parse:'+valType)
					continue;
				}
				baseData[key]=keyVal+(isString?'=;use':'=;parse:'+valType)
			}
		}
		baseData.requestTimeTemp=timeTemp
		baseData.verifyUseToObj=verifyUseToObj
	}catch(e){
		throw new Error(e);
	}
	return baseData
}


/**
 * 对象解密
 * @param {*} data 数据对象
 * @param {*} decryptKey 是否对字段运行解密
 * @returns Object 解密后的对象
 */
export function decryption(data,decryptKey=false){
	if(!data) return data
	let baseData = data
	try{
		const {requestTimeTemp,verifyUseToObj,...getData} = JSON.parse(JSON.stringify(data))
		for (const key in getData) {
			if (Object.hasOwnProperty.call(getData, key)) {
				const value = getData[key];
				if(!verifyUseToObj  || typeof value != 'string' || !value.includes('=;')) continue;
				const [valStr,mode]=value.split('=;')
				let trueVal = CryptoJS.AES.decrypt(valStr, SecretKey, {
					iv: iv,
					mode: CryptoJS.mode.CBC,
					padding: CryptoJS.pad.Pkcs7
				}).toString(CryptoJS.enc.Utf8)
				if(mode.includes('parse')) trueVal = JSON.parse(trueVal)
				let trueKey = key
				if(decryptKey){
					trueKey = CryptoJS.AES.decrypt(key, SecretKey, {
						iv: iv,
						mode: CryptoJS.mode.CBC,
						padding: CryptoJS.pad.Pkcs7
					}).toString(CryptoJS.enc.Utf8)
					delete getData[key]
				}
				getData[trueKey] = trueVal
			}
		}
		const dataVerify = CryptoJS.MD5(JSON.stringify({
			// ...getData,
			dataTimeTemp:requestTimeTemp,
			SecretKey:SecretKey.toString(CryptoJS.enc.Base64),
			iv:iv.toString(CryptoJS.enc.Base64)
		})).toString()
		if(verifyUseToObj != dataVerify){
			throw new Error('数据校验失败，可能已被篡改');
		}
		baseData=getData
	}catch(e){
		throw new Error(e);
	}
	return baseData
}//对象解密